﻿using MvvmCross.Core.ViewModels;
using Sidvall.Data;
using Sidvall.WorkItemManager.UI.Entities;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;

namespace Sidvall.WorkItemManager.UI.ViewModels
{
    public partial class WorkRetryPolicyViewModel
    {
        #region Public Members

        #region TreeItems

        private TreeItemCollection _TreeItems;
        public TreeItemCollection TreeItems
        {
            get
            {
                return _TreeItems;
            }
            set
            {
                if (_TreeItems != null)
                    _TreeItems.CollectionChanging -= OnTreeItemsCollectionChanging;
                _TreeItems = value;
                if (_TreeItems != null)
                    _TreeItems.CollectionChanging += OnTreeItemsCollectionChanging;
                RaisePropertyChanged("TreeItems");
            }
        }

        #endregion
        #region ActiveServerConnection

        private ServerConnection _ActiveServerConnection;
        public ServerConnection ActiveServerConnection
        {
            get
            {
                return _ActiveServerConnection;
            }
            set
            {
                _ActiveServerConnection = value;

                if (_ActiveServerConnection != null)
                {
                    if (_ActiveItem != null)
                        _ActiveItem.PropertyChanged -= OnActiveWorkerPropertyChanged;
                    _ActiveItem = null;
                }
                InitializeTreeItem();
            }
        }

        #endregion
        #region ActiveServerManager

        private Sidvall.WorkItemManager.UI.Entities.ServerManager _ActiveServerManager;
        public Sidvall.WorkItemManager.UI.Entities.ServerManager ActiveServerManager
        {
            get
            {
                return _ActiveServerManager;
            }
            set
            {
                _ActiveServerManager = value;
                RaisePropertyChanged("ActiveServerManager");
                RaisePropertyChanged("CanSave");
                RaisePropertyChanged("CanDelete");
                RaisePropertyChanged("CanEdit");
            }
        }

        #endregion
        #region ActiveItem

        private WorkRetryPolicy _ActiveItem;
        public WorkRetryPolicy ActiveItem
        {
            get
            {
                return _ActiveItem;
            }
            set
            {
                if (_ActiveItem != null)
                    _ActiveItem.PropertyChanged -= OnActiveWorkerPropertyChanged;
                _ActiveItem = value;
                if (_ActiveItem != null)
                {
                    _ActiveItem.PropertyChanged += OnActiveWorkerPropertyChanged;
                    _ActiveServerConnection = null;
                }
                InitializeTreeItem();
            }
        }

        #endregion
        #region ActiveTreeItem

        private TreeItem _ActiveTreeItem;
        public TreeItem ActiveTreeItem
        {
            get
            {
                return _ActiveTreeItem;
            }
            set
            {
                _ActiveTreeItem = value;
                RaisePropertyChanged("ActiveTreeItem");
            }
        }

        #endregion
        #region InformationIsVisible

        public bool InformationIsVisible
        {
            get
            {
                if (_ItemIsVisible)
                    return false;
                if ((this.ServerIsVisible) || (this.ItemIsVisible))
                    return false;
                return true;
            }
        }

        #endregion
        #region ServerIsVisible

        public bool ServerIsVisible
        {
            get
            {
                if (_ItemIsVisible)
                    return false;
                if (this.ActiveServerConnection != null)
                    return true;
                return false;
            }
        }

        #endregion
        #region ItemIsVisible

        private bool _ItemIsVisible = true;
        public bool ItemIsVisible
        {
            get
            {
                if (_ItemIsVisible)
                    return true;
                if (this.ActiveItem != null)
                    return true;
                return false;
            }
            set
            {
                _ItemIsVisible = value;
                RaisePropertyChanged("ItemIsVisible");
            }
        }

        #endregion
        #region CanAddTreeItem

        public bool CanAddTreeItem
        {
            get
            {
                if (this.ActiveServerConnection == null)
                    return false;
                if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkRetryPolicy, Sidvall.Security.Operations.UpdateItems))
                    return false;
                return true;
            }
        }

        #endregion
        #region CanDelete

        public bool CanDelete
        {
            get
            {
                if (this.ActiveItem == null)
                    return false;
                if (this.ActiveItem.WorkRetryPolicyId == null)
                    return false;
                if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkRetryPolicy, Sidvall.Security.Operations.UpdateItems))
                    return false;
                return true;
            }
        }

        #endregion
        #region CanEdit

        public bool CanEdit
        {
            get
            {
                if (this.ActiveItem == null)
                    return false;
                if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkRetryPolicy, Sidvall.Security.Operations.UpdateItems))
                    return false;
                return true;
            }
        }

        #endregion
        #region CanSave

        public bool CanSave
        {
            get
            {
                if (this.ActiveItem == null)
                    return false;
                if (!this.ActiveItem.DataRowStateIsDirty)
                    return false;
                if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkRetryPolicy, Sidvall.Security.Operations.UpdateItems))
                    return false;
                return true;
            }
        }

        #endregion
        #region AddTreeItemCaption

        public string AddTreeItemCaption
        {
            get
            {
                if (this.ActiveServerConnection != null)
                    return "Add condition";
                return null;
            }
        }

        #endregion
        #region TreeItemIsEnabled

        public bool TreeItemIsEnabled
        {
            get
            {
                if (this.ActiveTreeItem == null)
                    return false;
                return this.ActiveTreeItem.IsEnabled;
            }
        }

        #endregion

        #region ExportSettingsCommand

        public ICommand ExportSettingsCommand
        {
            get
            {
                return new MvxCommand(async () => await ExportSettingsAsync());
            }
        }

        #endregion
        #region ExportSettingsAsync

        public async Task ExportSettingsAsync()
        {
            if (this.ActiveItem == null)
                return;
            var item = new Net.Services.V1.WorkRetryPolicy();
            item.Import(this.ActiveItem, Sidvall.Data.CopySettings.FullCopyAll(Sidvall.Data.DataRowContextOption.None, null));
            await ViewModelManager.ExportSettingsAsync("Condition_" + this.ActiveItem.Name + ".txt", item);
        }

        #endregion
        #region ImportSettingsCommand

        public ICommand ImportSettingsCommand
        {
            get
            {
                return new MvxCommand(async () => await ImportSettingsAsync());
            }
        }

        #endregion
        #region ImportSettingsAsync

        public async Task ImportSettingsAsync()
        {
            Task task = null;

            if (this.ActiveServerConnection == null)
                return;
            try
            {
                var content = await ViewModelManager.ImportSettingsAsync();
                if (string.IsNullOrWhiteSpace(content))
                    return;
                var data = Sidvall.Serialization.SerializerManager.Current.Deserialize<Net.Services.V1.WorkRetryPolicy>(content);
                var item = new Sidvall.WorkItemManager.UI.Entities.WorkRetryPolicy();
                var copySettings = CopySettings.FullCopyAll(Sidvall.Data.DataRowContextOption.None, null);
                item.Import(data, copySettings);
                item.ServerConnectionId = this.ActiveServerConnection.ServerConnectionId;
                item = await item.SaveItemAsync();
                await ReloadAsync();
                var treeItem = (from o in this.TreeItems
                                where (o.ServerConnectionId == item.ServerConnectionId) && (o.ItemId == item.WorkRetryPolicyId)
                                select o).FirstOrDefault();
                if (treeItem != null)
                    this.ActiveTreeItem = treeItem;
            }
            catch (System.Exception ex)
            {
                task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
            }
            if (task != null)
                await task;
        }

        #endregion

        #region AddTreeItemCommand

        public ICommand AddTreeItemCommand
        {
            get
            {
                return new MvxCommand(async () => await AddTreeItemAsync());
            }
        }

        #endregion
        #region AddTreeItemAsync

        public async Task AddTreeItemAsync()
        {
            TreeItem treeItem;
            Task task = null;

            treeItem = null;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    if (this.ActiveServerConnection != null)
                    {
                        var item = new WorkRetryPolicy()
                        {
                            ServerConnectionId = this.ActiveServerConnection.ServerConnectionId,
                            Name = "** New retry policy **",
                        };
                        item = await item.SaveItemAsync();
                        await ReloadAsync();
                        treeItem = (from o in this.TreeItems
                                    where (o.ServerConnectionId == item.ServerConnectionId) && (o.ItemId == item.WorkRetryPolicyId)
                                    select o).FirstOrDefault();
                    }
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
            if (treeItem != null)
                this.ActiveTreeItem = treeItem;
        }

        #endregion
        #region DeleteActiveTreeItemCommand

        public ICommand DeleteActiveTreeItemCommand
        {
            get
            {
                return new MvxCommand(async () => await DeleteActiveTreeItemAsync());
            }
        }

        #endregion
        #region DeleteActiveTreeItemAsync

        public async Task DeleteActiveTreeItemAsync()
        {
            await DeleteTreeItemAsync(this.ActiveTreeItem);
        }

        #endregion
        #region SaveActiveTreeItemCommand

        public ICommand SaveActiveTreeItemCommand
        {
            get
            {
                return new MvxCommand(async () => await SaveActiveTreeItemAsync());
            }
        }

        #endregion
        #region SaveActiveTreeItemAsync

        public async Task SaveActiveTreeItemAsync()
        {
            Task task = null;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    if (this.ActiveItem != null)
                    {
                        this.ActiveItem = await this.ActiveItem.SaveItemAsync();
                    }
                    await ReloadAsync();
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion
        #region SelectTreeItemCommand

        public ICommand SelectTreeItemCommand
        {
            get
            {
                return new MvxCommand(async () => await SelectTreeItemAsync());
            }
        }

        #endregion
        #region SelectTreeItemAsync

        public async Task SelectTreeItemAsync()
        {
            Task task = null;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    if (this.ActiveTreeItem == null)
                    {
                        this.ActiveServerManager = null;
                        this.ActiveItem = null;
                    }
                    else if (this.ActiveTreeItem.IsServer)
                    {
                        this.ActiveServerManager = ServerConnection.GetServerManager(this.ActiveTreeItem.ServerConnectionId);
                        this.ActiveServerConnection = ServerConnection.GetServerConnection(this.ActiveTreeItem.ServerConnectionId);
                    }
                    else
                    {
                        this.ActiveServerManager = ServerConnection.GetServerManager(this.ActiveTreeItem.ServerConnectionId);
                        this.ActiveItem = await Sidvall.WorkItemManager.UI.SystemContext.Current.DataPortal.WorkRetryPolicyManager.GetItemByPrimaryKeyAsync(this.ActiveTreeItem.ServerConnectionId, this.ActiveTreeItem.ItemId.Value);
                    }
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion

        #region ReloadAsync

        public async Task ReloadAsync()
        {
            Task task = null;
            try
            {
                if (this.TreeItems == null)
                    return;
                await this.TreeItems.ReloadAsync(Sidvall.WorkItemManager.Data.TreeType.RetryPolicy);
            }
            catch (System.Exception ex)
            {
                task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
            }
            if (task != null)
                await task;
        }

        #endregion
        #region StartAsync

        protected override async Task StartAsync()
        {
            this.ItemIsVisible = false;
            this.TreeItems = TreeItemCollection.GetTreeItemCollection();
            await ReloadAsync();
        }

        #endregion

        #endregion
        #region Private Members

        #region DeleteTreeItemAsync

        private async Task DeleteTreeItemAsync(TreeItem item)
        {
            Task task = null;
            if (item == null)
                return;
            if (item.IsServer)
                return;
            using (var busyManager = new Sidvall.Data.BusyManager(this))
            {
                try
                {
                    var message = await Sidvall.UI.SystemContext.Current.DialogManager.ShowYesNoMessageAsync("Remove item: " + item.Name, "Are you sure?",
                        Sidvall.UI.Dialogs.MessageType.Question, false);
                    if (!message.AnswerIsYes)
                        return;
                    await Sidvall.WorkItemManager.SystemContext.Current.DataPortal.WorkRetryPolicyManager.DeleteItemByPrimaryKeyAsync(item.ServerConnectionId,
                        item.ItemId.Value);
                    if ((this.ActiveItem != null) && (this.ActiveItem.WorkRetryPolicyId == item.ItemId))
                        this.ActiveItem = null;
                    await ReloadAsync();
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion
        #region InitializeTreeItem

        private void InitializeTreeItem()
        {
            RaisePropertyChanged("ActiveServer");
            RaisePropertyChanged("ActiveItem");
            RaisePropertyChanged("InformationIsVisible");
            RaisePropertyChanged("ServerIsVisible");
            RaisePropertyChanged("ItemIsVisible");
            RaisePropertyChanged("CanSave");
            RaisePropertyChanged("CanDelete");
            RaisePropertyChanged("CanEdit");
            RaisePropertyChanged("CanAddTreeItem");
            RaisePropertyChanged("AddTreeItemCaption");
            RaisePropertyChanged("TreeItemIsEnabled");
        }

        #endregion

        #region OnActiveWorkerPropertyChanged

        private void OnActiveWorkerPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(e.PropertyName))
                return;
            RaisePropertyChanged("CanSave");
            RaisePropertyChanged("CanEdit");
            RaisePropertyChanged("TreeItemIsEnabled");
        }

        #endregion
        #region OnTreeItemsCollectionChanging

        private async void OnTreeItemsCollectionChanging(object sender, Sidvall.Business.CollectionChangedEventArgs e)
        {
            if (e.Action == Sidvall.Business.CollectionChangedAction.RemoveItem)
            {
                await DeleteTreeItemAsync(e.Item as TreeItem);
                e.Cancel = true;
            }
        }

        #endregion

        #endregion
    }
}